package smallChanges.statements;

import net.sourceforge.pmd.ast.ASTExpression;
import net.sourceforge.pmd.ast.ASTForInit;
import net.sourceforge.pmd.ast.ASTForStatement;
import net.sourceforge.pmd.ast.ASTForUpdate;
import net.sourceforge.pmd.ast.ASTStatement;
import net.sourceforge.pmd.ast.JavaParserVisitorAdapter;
import smallChanges.Tokenization.TokenSet;
import smallChanges.util.SCConstants;

/**
 * @author jspacco
 *
 */
public class ForStatementVisitor extends JavaParserVisitorAdapter implements SCConstants
{
	private TokenSet tokenSet;
	
	public ForStatementVisitor(TokenSet tokenSet) {
		this.tokenSet=tokenSet;
	}
	
	public static final boolean DEBUG=false;
	
	
	/* (non-Javadoc)
	 * @see net.sourceforge.pmd.ast.JavaParserVisitorAdapter#visit(net.sourceforge.pmd.ast.ASTStatement, java.lang.Object)
	 */
	@Override
	public Object visit(ASTStatement node, Object data)
	{
		if (data instanceof ForStatementHeader) {
			ForStatementHeader stmt=(ForStatementHeader)data;
			if (stmt.getBeginLine()>0) {
			    // If the update is empty, expand by one token
			    // to include the closing paren
			    if (stmt.getForUpdate()==null) {
			        stmt.expandByOneFollowingToken();
			        // if the condition is also empty, expand 
			        // by one token to include the second semi-colon
			        if (stmt.getCondition()==null) {
			            stmt.expandByOneFollowingToken();
			            // if the init is also empty, expand
			            // by one token to include the first semi-colon
			            if (stmt.getForInit()==null) {
			                stmt.expandByOneFollowingToken();
			            }
			        }
			    }
				return stmt;
			}
		}
		return super.visit(node, data);
	}

	/* (non-Javadoc)
	 * @see net.sourceforge.pmd.ast.JavaParserVisitorAdapter#visit(net.sourceforge.pmd.ast.ASTForInit, java.lang.Object)
	 */
	@Override
	public Object visit(ASTForInit node, Object data)
	{
		if (data instanceof ForStatementHeader) {
			ForStatementHeader header=(ForStatementHeader)data;
			MetaInformationAnnotation range=new MetaInformationAnnotation(tokenSet, FOR_INIT);
			range.setCoordinatesFromNode(node);
			header.setForInit(range);
			// set the ending coords of the loop header
			// to match the end of the init node
			header.setEndCoordsFromNode(node);
			// expand by one token to include the semi-colon
			header.expandByOneFollowingToken();
		}
		return super.visit(node, data);
	}
	
	/* (non-Javadoc)
	 * @see net.sourceforge.pmd.ast.JavaParserVisitorAdapter#visit(net.sourceforge.pmd.ast.ASTExpression, java.lang.Object)
	 */
	@Override
	public Object visit(ASTExpression node, Object data)
	{
		if (data instanceof ForStatementHeader) {
			ForStatementHeader header=(ForStatementHeader)data;
			MetaInformationAnnotation range=new MetaInformationAnnotation(tokenSet, FOR_CONDITION);
			range.setCoordinatesFromNode(node);
			header.setCondition(range);
			// set the ending coords of the loop header
            // to match the end of the condition
            header.setEndCoordsFromNode(node);
            // expand by one token to include the semi-colon
            header.expandByOneFollowingToken();
		}
		return super.visit(node, data);
	}

	/* (non-Javadoc)
	 * @see net.sourceforge.pmd.ast.JavaParserVisitorAdapter#visit(net.sourceforge.pmd.ast.ASTForStatement, java.lang.Object)
	 */
	@Override
	public Object visit(ASTForStatement node, Object data)
	{
		if (data instanceof StatementHeader) {
			StatementHeader header=(StatementHeader)data;
			// set the beginning and ending of the for loop to
			// just before the 'for' keyword
			header.setBeginLine(node.getBeginLine());
			header.setBeginColumn(node.getBeginColumn());
			header.setEndLine(node.getBeginLine());
			header.setEndColumn(node.getBeginColumn());
			header.setTokensFromRange();
			// expand to include the 'for' keyword
			header.expandByOneFollowingToken();
			// expand to include the open paren
			header.expandByOneFollowingToken();
			
			node.childrenAccept(this, header);
			return header;
		}
		return super.visit(node, data);
	}

	/* (non-Javadoc)
	 * @see net.sourceforge.pmd.ast.JavaParserVisitorAdapter#visit(net.sourceforge.pmd.ast.ASTForUpdate, java.lang.Object)
	 */
	@Override
	public Object visit(ASTForUpdate node, Object data)
	{
		if (data instanceof ForStatementHeader) {
			ForStatementHeader header=(ForStatementHeader)data;
			MetaInformationAnnotation range=new MetaInformationAnnotation(tokenSet, FOR_UPDATE);
			range.setCoordinatesFromNode(node);
			header.setForUpdate(range);
			// set the ending coords of the loop header
            // to match the end of the update
            header.setEndCoordsFromNode(node);
            // expand by one token to include the closing right paren
            header.expandByOneFollowingToken();
		}
		return super.visit(node, data);
	}

}
